/*
* Copyright (c) 2010 Michael Collins
*
* This file is part of TerraFirma.
*
* TerraFirma is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* TerraFirma is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TerraFirma.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETWORK_PIPE_H
#define NETWORK_PIPE_H

#include <boost/thread/thread.hpp>
#include <queue>
#include "message_network.h"
#include <string.h>

namespace engine
{
    //Forward declarations They just need private member access, so this is safe
    class mpi;
    class network_thread;

    class network_pipe //: public message_queue<inter_network_msg>
    {
    public:
        network_pipe(boost::condition_variable& r);
        ~network_pipe();

        //Most of this is from message_queue, but the virtual functions would be overloaded so it's not worth it
        bool isempty() const
        {
            return empty;
        }

        const inter_network_msg& front() const
        {
            return queue.front();
        }

        void pop();

        //Resets the sequence numbers for a specified host (called when that host disconnects)
        void reset(hostid h)
        {
            seqs[h] = 0;
        }

    protected:
    private:
        //Queues a message up to be sent off to a remote host
        void enqueue(hostid dst, const message_header* msg);
        //Queues up a message to be sent off to a remote host
        //It is guaranteed to be received, but not necessarily in order, and possibly processed more than once
        void enqueue_ensured(hostid dst, const message_header* msg);
        //Queues up a message to be sent off to a remote host
        //This offers TCP level ensurement. Packets are received exactly once, and in order.
        void enqueue_ordered(hostid dst, const message_header* msg);

        //Packet sequence numbers of each of the hosts
        //(in the case that this is a client connecting to a remote
        //server, only use seqs[0]
        uint16_t seqs [256];

        boost::condition_variable& read; //Refers to the condition variable
        boost::mutex mut; //Queue guard
        std::queue<inter_network_msg> queue;
        bool empty;

        friend class mpi;
        friend class network_thread;
    };

}

#endif // NETWORK_PIPE_H
